iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 12
0
自我挑戰組

Access VBA的眉眉角角系列 第 12

Access VBA 的眉眉角角Day12: 檔案清單的建立

  • 分享至 

  • xImage
  •  

使用Access資料庫可以便於分析資料,因此有許多人會將實驗設備產生的純文字報表檔轉入資料庫內分析,在轉這些檔案之前,總要先產生清單,然後再逐一處理,這部份我也製作了一個程式進行,以便於批次處理相關檔案。除此之外,也可應用於管理檔案,可以便於比對檔名,篩選過大檔案等功能。

程式中會運用到Terry Kreft撰寫的BrowseFolder子程式,以便於選擇資料夾,我們這裡先列出:

建議可建立另一模組儲存以下程式碼,以便於區隔開,以下程式主要是宣告一些變數與呼叫系統檔「shell32.dll」中的「SHGetPathFromIDList」功能

'http://access.mvps.org/access/api/api0002.htm
'
'************** Code Start **************
'This code was originally written by Terry Kreft.
'It is not to be altered or distributed,
'except as part of an application.
'You are free to use it in any application,
'provided the copyright notice is left unchanged.
'
'Code courtesy of
'Terry Kreft

Private Type BROWSEINFO
  hOwner As Long
  pidlRoot As Long
  pszDisplayName As String
  lpszTitle As String
  ulFlags As Long
  lpfn As Long
  lParam As Long
  iImage As Long
End Type

Private Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias _
            "SHGetPathFromIDListA" (ByVal pidl As Long, _
            ByVal pszPath As String) As Long
            
Private Declare Function SHBrowseForFolder Lib "shell32.dll" Alias _
            "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) _
            As Long
            
Private Const BIF_RETURNONLYFSDIRS = &H1

此為瀏覽資料夾的主程式:

Public Function BrowseFolder(szDialogTitle As String) As String
  Dim X As Long, bi As BROWSEINFO, dwIList As Long
  Dim szPath As String, wPos As Integer
  
    With bi
        .hOwner = hWndAccessApp
        .lpszTitle = szDialogTitle
        .ulFlags = BIF_RETURNONLYFSDIRS
        .pidlRoot = 0
    End With
    
    dwIList = SHBrowseForFolder(bi)
    szPath = Space$(512)
    X = SHGetPathFromIDList(ByVal dwIList, ByVal szPath)
    
    If X Then
        wPos = InStr(szPath, Chr(0))
        BrowseFolder = Left$(szPath, wPos - 1)
    Else
        BrowseFolder = vbNullString
    End If
End Function
'*********** Code End *****************

下面這兩個程式,用於裁剪字串:

Function CutLeft(strData As String, strCut As String) As String
    '依照strCut的字元數,刪除strData左邊的字元
    CutLeft = Mid(strData, Len(strCut) + 1, Len(strData) - Len(strCut))
End Function

Function CutRight(strData As String, strCut As String) As String
    '依照strCut的字元數,刪除strData右邊的字元
    CutRight = Mid(strData, 1, Len(strData) - Len(strCut))
End Function

接下來,我們列出產生檔案清單的相關程式,主程式的部份也是參考網路上的資源再加以修改,各位也可以依照自己的需求調整程式:

'建立檔案清單
Sub PutPathFile()
    '參考來源
    'http://stackoverflow.com/questions/14245712/cycle-through-sub-folders-and-files-in-a-user-specified-root-directory

    Dim fso As Object 'FileSystemObject
    Dim fldStart As Object 'Folder
    Dim fld As Object 'Folder
    Dim fl As Object 'File
    Dim Mask As String
    Dim WorkTime, LastImpTime, StartImpTime
    Dim strTable As String
    
    '資料表名稱
    strTable = "ImpData"
    
    '如果資料表不存在,則建立一組
    If ifObjectExists(strTable) = False Then

        DoCmd.RunSQL "CREATE TABLE " & strTable & " " & _
                     "(" & _
                     " [FullPath] MEMO, " & _
                     " [Base] Text(255), " & _
                     " [Path] MEMO, " & _
                     " [File] Text(255), " & _
                     " [Ext]  Text(255), " & _
                     " [DateCreated] DATETIME, " & _
                     " [DateLastAccessed] DATETIME, " & _
                     " [DateLastModified] DATETIME, " & _
                     " [Size] DOUBLE, " & _
                     " [Attributes] SHORT " & _
                     ")"
    End If
    
    Dim objActSht As Object
    
    Set fso = CreateObject("scripting.FileSystemObject")
    
    '開啟BrowseFolder API來選擇資料夾
    strFolder = BrowseFolder("請選擇資料夾")
    
    strFolder = InputBox("請確認資料夾路徑:", , strFolder)
    
    '如果沒有選擇的話則離開程式
    If Len(strFolder) = 0 Then Exit Sub
    
    '清空原始資料
    If MsgBox("是否清空舊清單?", vbOKCancel) = vbOK Then
        RunSQL "DELETE FROM " & strTable
    End If
    
    '開始時間
    StartImpTime = Now
    
    Set fldStart = fso.GetFolder(strFolder)
    
        
    'On Error Resume Next
    
    Mask = "*.*"
    Debug.Print fldStart.path & "\"
    
    Call ListFiles(fso, fldStart, Mask, strTable)
    
    For Each fld In fldStart.SubFolders
        Call ListFiles(fso, fld, Mask, strTable)
        Call ListFolders(fso, fld, Mask, strTable)
    Next
    
    '結束時間
    LastImpTime = Now
    
    '儲存最後匯入時間
    Call ConfigSave("LastImpTime", Format(LastImpTime))
    
    WorkTime = LastImpTime - StartImpTime
    MsgBox "處理時間:" & Format(WorkTime, "HH:MM:SS")
    
End Sub

列出資料夾列表,然後再Call列出檔案列表與列出資料夾列表,如此循環下去達到遍歷所有資料的功能

Sub ListFolders(fso As Object, fldStart As Object, Mask As String, strTable As String)
    Dim fld As Object 'Folder
    For Each fld In fldStart.SubFolders
        Call ListFiles(fso, fld, Mask, strTable)
        Call ListFolders(fso, fld, Mask, strTable)
    Next

End Sub

列出檔案列表,然後將檔案的相關屬性寫入資料庫

Sub ListFiles(fso As Object, fld As Object, Mask As String, strTable As String)
    Dim fl As Object 'File
    Dim m As Object
    Dim strFile As String
    Dim strExt As String
    Dim strBase As String
    Dim strPath As String
    
    Set m = CurrentDb.OpenRecordset("SELECT * FROM " & strTable & "")
    
    For Each fl In fld.Files
        
        '把XP建立的"Thumbs.db"檔案略過
        If fl.Name Like Mask And fl.Name <> "Thumbs.db" Then

            m.AddNew
            m("FullPath") = fl.path
            strBase = fl.drive.path
            strPath = fl.parentfolder.path
            
            '如果有資料夾,則將路徑的部份去除strBase
            If Len(strPath) > Len(strBase) + 1 Then '加斜線的字元
                strPath = CutLeft(strPath, strBase)
            End If
            
            m("Base") = strBase
            m("Path") = strPath
            
            strFile = fl.Name
            strExt = fso.GetExtensionName(fl.Name)
            
            '如果有副檔名strExt,則將檔案全名的部份去除副檔名
            If Len(strExt) > 0 Then
                strFile = CutRight(strFile, "." & strExt)
            End If
            
            m("File") = strFile
            m("Ext") = strExt
            
            m("Attributes") = fl.Attributes
            m("DateCreated") = fl.DateCreated
            m("DateLastAccessed") = fl.DateLastAccessed
            m("DateLastModified") = fl.DateLastModified
            m("Size") = fl.Size
            m.Update
        End If
    Next
    Set m = Nothing

End Sub

準備好用,只要執行「PutPathFile()」子程式,即可開啟「瀏覽資料夾」視窗
http://ithelp.ithome.com.tw/upload/images/20161213/20007221VSJtX8HOqW.png

選擇後,會帶出另一視窗確認路徑,如果要填入其他路徑,例如網域上的其他電腦分享資料夾亦可填上
http://ithelp.ithome.com.tw/upload/images/20161213/20007221icYplQTN92.png

接下來會詢問是否清除清單,如果按取消,則會保留清單,然後再加上新資料
http://ithelp.ithome.com.tw/upload/images/20161213/20007221flSHtwPdxC.png

最後會列出匯入的處理時間
http://ithelp.ithome.com.tw/upload/images/20161213/20007221VyFk5aNiD6.png

清單建立完成後,可開啟「ImpData」資料表來查閱轉入的資料
http://ithelp.ithome.com.tw/upload/images/20161213/20007221iurloYZZ7G.png

以上的分享,希望對各位有幫助。


上一篇
Access VBA 的眉眉角角Day11: 資料夾與檔案的處理
下一篇
Access VBA 的眉眉角角Day13: 列出資料表與欄位清單
系列文
Access VBA的眉眉角角30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言